package com.game.modular.game.battle.info.roundInfo;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.game.modular.game.battle.info.roundInfo.domain.PvpBattleStatisticsInfo;
import com.game.modular.game.battle.info.roundInfo.dto.PvpBattleStatisticsPlayerInfo;
import com.game.modular.game.playerAssets.domain.PlayerHero;
import com.game.modular.game.playerInfo.service.PlayerServiceImpl;
import com.game.modular.game.playerMatch.domain.PvpCity;

import com.game.modular.game.playerMatch.service.PlayerMatchServiceImpl;
import lombok.extern.slf4j.Slf4j;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.game.modular.game.playerMatch.mapper.PvpBattleStatisticsInfoMapper;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * pvp战斗统计信息
 *
 * @author cxy
 * @since 2024-09-05 14:56:05
 */
@Slf4j
@Service
public class PvpBattleStatisticsInfoServiceImpl extends ServiceImpl<PvpBattleStatisticsInfoMapper, PvpBattleStatisticsInfo> implements IService<PvpBattleStatisticsInfo> {
    private static final String RedisKey = "battle:%d:StatisticsInfo";
    @Resource
    private RedisTemplate<Object, Object> redisTemplate;
    @Resource
    private ValueOperations<Object, PvpBattleStatisticsInfo> valueOperations;
    @Resource
    private PvpBattleStatisticsInfoMapper pvpBattleStatisticsInfoMapper;
    @Resource
    private PlayerServiceImpl playerServiceImpl;
    @Resource
    private PlayerMatchServiceImpl playerMatchServiceImpl;

    public PvpBattleStatisticsInfo init(
            Long playerId,
            Long defenseCityId,
            List<PlayerHero> attackSide,
            List<PlayerHero> defenseSide,
            Long currentMatchId,
            PvpCity pvpCity
    ) {
        PvpBattleStatisticsInfo build = PvpBattleStatisticsInfo.builder()
                .matchId(currentMatchId)
                .cityId(defenseCityId)
                .attackPlayerUid(playerId)
                .attackPlayerInfo(PvpBattleStatisticsPlayerInfo.init(attackSide))
                .defendPlayerUid(pvpCity.getOwnerUid() == null ? 0 : pvpCity.getOwnerUid())
                .defendPlayerInfo(PvpBattleStatisticsPlayerInfo.init(defenseSide))
                .startTime(new Date())
                .build();
        insert(build);
        return build;
    }


    public void insert(PvpBattleStatisticsInfo pvpBattleStatisticsInfo) {
        super.save(pvpBattleStatisticsInfo);
        if (pvpBattleStatisticsInfo.getBattleId() == null) {
            throw new RuntimeException("battleId不能为空");
        }
        saveCache(pvpBattleStatisticsInfo);
    }

    public void saveCache(PvpBattleStatisticsInfo pvpBattleStatisticsInfo) {
        String key = String.format(RedisKey, pvpBattleStatisticsInfo.getBattleId());
        valueOperations.set(key, pvpBattleStatisticsInfo, 12, TimeUnit.HOURS);
    }

    public PvpBattleStatisticsInfo selectCache(Long id) {
        String key = String.format(RedisKey, id);
        return valueOperations.get(key);
    }

    public boolean updateById(PvpBattleStatisticsInfo pvpBattleStatisticsInfo) {
        boolean b = super.updateById(pvpBattleStatisticsInfo);
        saveCache(pvpBattleStatisticsInfo);
        return b;
    }

    public PvpBattleStatisticsInfo getById(Long id) {
        PvpBattleStatisticsInfo pvpBattleStatisticsInfo = selectCache(id);
        if (pvpBattleStatisticsInfo == null) {
            pvpBattleStatisticsInfo = super.getById(id);
            saveCache(pvpBattleStatisticsInfo);
        }
        return pvpBattleStatisticsInfo;
    }


    public PvpBattleStatisticsPlayerInfo.HeroInfo getHeroInfo(
            Long battleId, Integer rankCamp, Long actWJId
    ) {
        PvpBattleStatisticsInfo pvpBattleStatisticsInfo = getById(battleId);
        PvpBattleStatisticsPlayerInfo actionPlayerInfo = pvpBattleStatisticsInfo.obtainActionPlayerInfo(rankCamp);
        return actionPlayerInfo.getHeroInfo(actWJId);
    }

    public PvpBattleStatisticsPlayerInfo.HeroInfo.SkillInfo getSkillInfo(
            Long battleId, Integer rankCamp, Long actWJId, Long coreSkillStarId
    ) {
        PvpBattleStatisticsPlayerInfo.HeroInfo heroInfo = getHeroInfo(battleId, rankCamp, actWJId);
        return heroInfo.getSkillInfo(coreSkillStarId);
    }

    public void updateSkillInfo(
            Long battleId, Integer rankCamp, Long actWJId, PvpBattleStatisticsPlayerInfo.HeroInfo.SkillInfo skillInfo
    ) {
        PvpBattleStatisticsInfo pvpBattleStatisticsInfo = getById(battleId);
        PvpBattleStatisticsPlayerInfo actionPlayerInfo = pvpBattleStatisticsInfo.obtainActionPlayerInfo(rankCamp);
        actionPlayerInfo.setSkillInfo(actWJId, skillInfo);
        pvpBattleStatisticsInfo.updateActionPlayerInfo(rankCamp, actionPlayerInfo);
        updateById(pvpBattleStatisticsInfo);
    }

    public void updateHeroInfo(
            Long battleId, Integer rankCamp, PvpBattleStatisticsPlayerInfo.HeroInfo heroInfo
    ) {
        PvpBattleStatisticsInfo pvpBattleStatisticsInfo = getById(battleId);
        PvpBattleStatisticsPlayerInfo actionPlayerInfo = pvpBattleStatisticsInfo.obtainActionPlayerInfo(rankCamp);
        actionPlayerInfo.setHeroInfo(heroInfo);
        pvpBattleStatisticsInfo.updateActionPlayerInfo(rankCamp, actionPlayerInfo);
        updateById(pvpBattleStatisticsInfo);
    }

    public List<PvpBattleStatisticsInfo> battleStatisticsInfoList(
            @NotNull(message = "playerId不能为空") Long playerId
    ) {
        Long currentMatchId = playerMatchServiceImpl.currentMatchId(playerId);
        LambdaQueryWrapper<PvpBattleStatisticsInfo> wrapper =
                new LambdaQueryWrapper<>();
        // 攻防包含playerId 返回
        wrapper.eq(PvpBattleStatisticsInfo::getMatchId, currentMatchId);
        wrapper.or(w -> w
                .eq(PvpBattleStatisticsInfo::getAttackPlayerUid, playerId)
                .or()
                .eq(PvpBattleStatisticsInfo::getDefendPlayerUid, playerId));
        // battleId 倒叙 最新排
        wrapper.orderByDesc(PvpBattleStatisticsInfo::getBattleId);
        // 分页
        wrapper.last("LIMIT 0,100");
        return list(wrapper);
    }

    public void collection(Long battleId) {
        PvpBattleStatisticsInfo pvpBattleStatisticsInfo = new PvpBattleStatisticsInfo();
        pvpBattleStatisticsInfo.setBattleId(battleId);
        pvpBattleStatisticsInfo.setIsCollect(1);
        pvpBattleStatisticsInfo.updateById();
    }

    public void readCurrentIntraBureauCombatInformation(Long battleId) {
        PvpBattleStatisticsInfo pvpBattleStatisticsInfo = new PvpBattleStatisticsInfo();
        pvpBattleStatisticsInfo.setBattleId(battleId);
        pvpBattleStatisticsInfo.setIsRead(1);
        pvpBattleStatisticsInfo.updateById();
    }

    /**
     * 统计技能释放次数
     */
    public void countTheNumberOfSkillReleases(
            Long battleId, PlayerHero actWJ, Long coreSkillStarId
    ) {
        Integer rankCamp = actWJ.getRankCamp();
        Long actWJId = actWJ.getId();
        // 更新技能使用次数
        PvpBattleStatisticsPlayerInfo.HeroInfo.SkillInfo skillInfo =
                getSkillInfo(battleId, rankCamp, actWJId, coreSkillStarId);
        skillInfo.setCount(skillInfo.getCount() + 1);
        updateSkillInfo(battleId, rankCamp, actWJId, skillInfo);
    }
}
